package com.zmj.sy.mom.srv.aps.utils.diff;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.zmj.sy.mom.srv.aps.bean.entity.order.*;
import com.zmj.sy.mom.srv.aps.bean.vo.consistency.ConsistencyCheckDataResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.consistency.ConsistencyCheckReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.order.OrderExternalSyncErrorResVo;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import com.zmj.sy.mom.srv.aps.utils.WorkshopProp;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Component
public class ErpDiffRule implements DiffRule {

    private final ImportErpOrderMapper importErpOrderMapper;
    private final ImportErpBomMapper importErpBomMapper;
    private final OrderMapper orderMapper;
    private final OrderBomMapper orderBomMapper;
    private final ImportErpMaterMapper importErpMaterMapper;
    private final ImportErpWorkOrderDetailMapper importErpWorkOrderDetailMapper;
    private final ImportErpMappingMapper importErpMappingMapper;
    private final ImportErpWorkOrderMapper importErpWorkOrderMapper;

    @Transactional(readOnly = true)
    @Override
    public List<ConsistencyCheckDataResVo> getData(ConsistencyCheckReqVo reqVo) {

        List<OrderExternalSyncErrorResVo> errorList = new ArrayList<>();

        List<ImportErpMapping> importErpMappings = importErpMappingMapper.selectList(null);

        List<ImportErpOrder> list = importErpOrderMapper.lambdaQuery()
                .eq(ImportErpOrder::getOrderCode, reqVo.getConstructionCode())
                .list();

        if(list.size() > 1){
            throw SyExceptionUtils.e("存在多个相同的施工号");
        }

        if(CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }

        List<Order> orderList = orderMapper.lambdaQuery()
                .eq(Order::getConstructNo, reqVo.getConstructionCode())
                .in(Order::getOrderType, 1, 4)
                .list();

        if(orderList.stream().map(Order::getConstructNo).distinct().count() > 1){
            throw SyExceptionUtils.e("存在多个匹配上的施工号");
        }


        ImportErpOrder importErpOrder = list.get(0);

        List<ImportErpBom> erpBomList = importErpBomMapper.lambdaQuery()
                .eq(ImportErpBom::getErpOrderId, importErpOrder.getId())
                .ne(ImportErpBom::getStatusId, "R")
                .apply(" material_code not like '010%' and material_code not like '020%'  and material_code not like '050%'  and material_code not like '060%' ")
                .list();

        List<OrderBom> syncErpCode = new ArrayList<>();
        for (Order order : orderList) {
            if(!order.getMaterName().matches("(顶梁|底座|掩护梁)[一|二|三|四|五|六|七]拼")){
                List<OrderBom> list1 = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, order.getId()).eq(OrderBom::getLevel, 2).list();
                syncErpCode.addAll(list1);
            } else {
                List<OrderBom> list1 = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, order.getId()).eq(OrderBom::getLevel, 1).list();
                syncErpCode.addAll(list1);
            }
        }

        List<ImportErpBom> topErpBomList = syncErpCode.stream()
                .flatMap(s -> erpBomList.stream().filter(e -> e.getMaterialCode().equals(s.getErpCode()) && e.getPmCode().equals(s.getErpParentCode())))
                .collect(Collectors.toList());

        // 获取所有的子节点
        List<ImportErpBom> allBomTree = findAllTree(importErpOrder);

//        Map<String, Map<String, ImportErpMapping>> erpMesOpMapping = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));
//        Map<String, List<ImportErpBom>> bomPmCodeMap = erpBomList.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
//        Map<String, List<ImportErpWorkOrder>> workOrderCodeMap = erpWorkOrderList.stream().collect(Collectors.groupingBy(ImportErpWorkOrder::getMaterialCode));
//        Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap = workOrderDetailListAll.stream().collect(Collectors.groupingBy(ImportErpWorkOrderDetail::getMaterialCode));
//        Map<String, ImportErpBom> parentBom = erpBomList.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));

        List<ConsistencyCheckDataResVo> allOrderBomList = new ArrayList<>();
        for (ImportErpBom currentBom : topErpBomList) {

            // 获取可用的的子节点
            List<ImportErpBom> bomChildren = findBomChildren(currentBom);
            List<String> materCodeList = bomChildren.stream().map(ImportErpBom::getMaterialCode).collect(Collectors.toList());

            // 获取所有的物料信息组成Map，供BOM使用
            List<ImportErpMater> materList = getMaterMap(currentBom.getErpOrderId(), materCodeList);

            // 获取所有的工单信息组成Map，供BOM使用
            List<ImportErpWorkOrder> erpWorkOrderList = getWorkOrderMap(currentBom.getErpOrderId(), materCodeList);

            // 获取所有的工单明细组成Map，供BOM使用
            List<ImportErpWorkOrderDetail> workOrderDetailList = getWorkOrderDetailMap(currentBom.getErpOrderId(), materCodeList);

            // 转换订单
            Optional<ImportErpMater> first = materList.stream().filter(e -> e.getMaterialCode().equals(currentBom.getMaterialCode())).findFirst();
            if (!first.isPresent()) {
                throw SyExceptionUtils.e("找不到对应的物料信息");
            }

//            Map<String, ImportErpMater> materCodeMap = materList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, Function.identity(), (e1, e2) -> e1));

            Order order = conversionOrder(importErpOrder, currentBom, first.get(), errorList);
            // 转换BOM
            List<OrderBom> orderBomList = conversionBom(order, importErpOrder, allBomTree, bomChildren, materList, erpWorkOrderList, workOrderDetailList, importErpMappings, errorList);

            if(CollUtil.isNotEmpty(orderBomList)){
//                allOrderBomList.addAll(orderBomList);

                List<ConsistencyCheckDataResVo> collect = orderBomList.stream()
                        .filter(e -> e.getWorkChain().contains("JG") || e.getWorkChain().contains("HG"))
                        .map(e -> {
                            ConsistencyCheckDataResVo vo = new ConsistencyCheckDataResVo();
                            vo.setWorkOrderCode(e.getWorkOrderCode());
                            vo.setConstructionCode(order.getConstructNo());
                            vo.setErpCode(e.getErpCode());
                            vo.setDrawCode(e.getDrawing());
                            vo.setPlmId(e.getPlmId());
                            vo.setMaterName(e.getMaterName());
                            vo.setTotalCount(e.getTotalCount().intValue());
                            String[] split = e.getStandards().split("δ");

//                            if(split.length == 2){
//                                vo.setMaterial(split[0].trim());
//                                vo.setThickness(Integer.parseInt(split[1].trim()));
//                            } else {
//                                vo.setMaterial(e.getTexture());
//                                vo.setThickness(e.getMaterHigh());
//                            }

                            if (!StringUtils.hasText(e.getTexture())) {
                                vo.setMaterial(split[0].trim());
                            } else {
                                vo.setMaterial(e.getTexture());
                            }
                            if (e.getMaterHigh() == null) {
                                vo.setThickness(Integer.parseInt(split[1].trim()));
                            } else {
                                vo.setThickness(e.getMaterHigh());
                            }

                            vo.setProcessChain(e.getWorkChain());


                            return vo;
                        })
                        .filter(e -> e.getProcessChain().contains("JG") || e.getProcessChain().contains("HG"))
                        .collect(Collectors.toList());

                if(CollUtil.isNotEmpty(collect)){
                    allOrderBomList.addAll(collect);
                }

            }
        }

        Collection<ConsistencyCheckDataResVo> values = allOrderBomList.stream().collect(Collectors.toMap(ConsistencyCheckDataResVo::getWorkOrderCode, Function.identity(), (e1, e2) -> {
            e1.setTotalCount(e1.getTotalCount() + e2.getTotalCount());
            return e1;
        })).values();

        return new ArrayList<>(values);
        /*

        List<ImportErpOrder> list = importErpOrderMapper.lambdaQuery()
                .like(ImportErpOrder::getOrderCode, reqVo.getConstructionCode())
                .list();

        if(list.size() > 1){
            throw SyExceptionUtils.e("存在多个相同的施工号");
        }

        if(CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }

        List<Order> orderList = orderMapper.lambdaQuery()
                .eq(Order::getConstructNo, reqVo.getConstructionCode())
                .in(Order::getOrderType, 1, 4)
                .list();

        if(CollUtil.isEmpty(orderList)){
            throw SyExceptionUtils.e("没有找到对应的订单");
//            return new ArrayList<>();
        }

        if(orderList.stream().map(Order::getConstructNo).distinct().count() > 1){
            throw SyExceptionUtils.e("存在多个匹配上的施工号");
        }

        ImportErpOrder importErpOrder = list.get(0);

        List<ImportErpBom> erpBomList = importErpBomMapper.lambdaQuery()
                .eq(ImportErpBom::getErpOrderId, importErpOrder.getId())
                .ne(ImportErpBom::getStatusId, "R")
                .apply(" material_code not like '010%' and material_code not like '020%'  and material_code not like '050%'  and material_code not like '060%' ")
                .list();

        List<OrderBom> syncErpCode = new ArrayList<>();
        for (Order order : orderList) {
            if(order.getMaterCode().equals(order.getSerialCode())){
                List<OrderBom> list1 = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, order.getId()).eq(OrderBom::getLevel, 2).list();
                syncErpCode.addAll(list1);
            } else {
                List<OrderBom> list1 = orderBomMapper.lambdaQuery().eq(OrderBom::getOrderId, order.getId()).eq(OrderBom::getLevel, 1).list();
                syncErpCode.addAll(list1);
            }
        }

        List<ImportErpBom> topErpBomList = syncErpCode.stream()
                .flatMap(s -> erpBomList.stream().filter(e -> e.getMaterialCode().equals(s.getErpCode()) && e.getPmCode().equals(s.getErpParentCode())))
                .collect(Collectors.toList());

        Map<String, List<ImportErpBom>> childrenMap = erpBomList.stream().filter(e->e.getPmCode() != null).collect(Collectors.groupingBy(ImportErpBom::getPmCode));


        List<ImportErpWorkOrderDetail> list1 = importErpWorkOrderDetailMapper.lambdaQuery().eq(ImportErpWorkOrderDetail::getErpOrderId, importErpOrder.getId()).list();

        Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));


        Map<String, List<ImportErpWorkOrderDetail>> workOrderCodeMaterialCodeMap = list1.stream()
                .collect(
                    Collectors.groupingBy(
                            ImportErpWorkOrderDetail::getMaterialCode
                    )
                );

        List<ImportErpMater> materList = importErpMaterMapper.lambdaQuery()
                .eq(ImportErpMater::getErpOrderId, importErpOrder.getId())
                .list();



        Map<String, ImportErpMater> materMap = materList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, e -> e));






        List<ImportErpBom> all = new ArrayList<>(topErpBomList);
        List<ImportErpBom> parent = new ArrayList<>(topErpBomList);
        while(CollUtil.isNotEmpty(parent)){
            List<ImportErpBom> children = new ArrayList<>();
            for (ImportErpBom parentBom : parent) {
                List<ImportErpBom> childList = childrenMap.get(parentBom.getMaterialCode());
                if(CollUtil.isEmpty(childList)){
                    continue;
                }
                children.addAll(childList);
            }
            if(CollUtil.isEmpty(children)){
                break;
            }

            all.addAll(children);
            parent = children;
        }

        all.removeIf(e->{

            ImportErpMater importErpMater = materMap.get(e.getMaterialCode());
            if(importErpMater == null){
                return true;
            }

            List<ImportErpWorkOrderDetail> importErpWorkOrderDetails = workOrderCodeMaterialCodeMap.get(e.getMaterialCode());
            if (CollUtil.isEmpty(importErpWorkOrderDetails)) {
                return true;
            }
            importErpWorkOrderDetails.sort(Comparator.comparing(ImportErpWorkOrderDetail::getSeq));

            List<OrderPhase> orderPhaseList = new ArrayList<>();

            for (ImportErpWorkOrderDetail detail : importErpWorkOrderDetails) {
                OrderPhase phase = new OrderPhase();
                if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
                    if (!detail.getOpCode().trim().startsWith("170")) {
                        continue;
                    }
                    continue;

                }
                ImportErpMapping importErpMapping = null;
                if (detail.getOpCode().startsWith("129")) {
                    importErpMapping = erpMesOpMappingMap.get("129002").get("Z206");
                } else {
                    importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());
                }

                if (importErpMapping == null) {
                    continue;
                }
                String phaseCodeCount = importErpMapping.getMesWorkPhase();

                phase.setPhaseCode(phaseCodeCount);
                phase.setPhaseName(importErpMapping.getApsPhaseName());

                orderPhaseList.add(phase);
            }

            long count = orderPhaseList.stream().filter(e2 -> e2.getPhaseCode().equals("JG") || e2.getPhaseCode().equals("HG")).count();
            if (count < 1) {
                return true;
            }

            return false;

        });

        List<ConsistencyCheckDataResVo> collect = all.stream()
                .map(e -> {
                    ConsistencyCheckDataResVo vo = new ConsistencyCheckDataResVo();
                    ImportErpMater importErpMater = materMap.get(e.getMaterialCode());
                    if(importErpMater == null){
                        return vo;
                    }
                    vo.setConstructionCode(importErpOrder.getOrderCode());
                    vo.setPlmId(importErpMater.getPlmId());
                    vo.setDrawCode(importErpMater.getPaintCode());
                    vo.setTotalCount(Integer.parseInt(e.getReqQty()));
                    vo.setMaterial(importErpMater.getMaterial());
                    vo.setMaterName(e.getMaterialName());
                    String[] split = e.getGrade().split("δ");
                    vo.setMaterial(split[0].trim());
                    vo.setThickness(Integer.parseInt(split[1]));
                    vo.setWorkOrderCode(e.getWorkOrderCode());
                    vo.setConstructionCode(e.getOrderCode());
                    vo.setErpCode(e.getMaterialCode());
                    return vo;
                })
                .filter(e -> e.getPlmId() != null)
                .collect(Collectors.toList());

        Map<String, ConsistencyCheckDataResVo> collect1 = collect.stream().collect(Collectors.toMap(ConsistencyCheckDataResVo::getPlmId, e -> e, (e1, e2) -> {
            e1.setTotalCount(e1.getTotalCount() + e2.getTotalCount());
            return e1;
        }));

        return new ArrayList<>(collect1.values());
        */
    }

    public List<OrderBom> conversionBom(Order order, ImportErpOrder importErpOrder, List<ImportErpBom> allBomTree, List<ImportErpBom> bomChildren, List<ImportErpMater> erpMaterList, List<ImportErpWorkOrder> erpWorkOrderList, List<ImportErpWorkOrderDetail> workOrderDetailListAll, List<ImportErpMapping> importErpMappings, List<OrderExternalSyncErrorResVo> errorList) {
        Map<String, Map<String, ImportErpMapping>> erpMesOpMapping = importErpMappings.stream().collect(Collectors.groupingBy(ImportErpMapping::getErpOpCode, Collectors.toMap(ImportErpMapping::getErpOp, Function.identity(), (e1, e2) -> e1)));
        Map<String, List<ImportErpBom>> bomPmCodeMap = allBomTree.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        Map<String, ImportErpMater> materCodeMap = erpMaterList.stream().collect(Collectors.toMap(ImportErpMater::getMaterialCode, Function.identity(), (e1, e2) -> e1));
        Map<String, List<ImportErpWorkOrder>> workOrderCodeMap = erpWorkOrderList.stream().collect(Collectors.groupingBy(ImportErpWorkOrder::getMaterialCode));
        Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap = workOrderDetailListAll.stream().collect(Collectors.groupingBy(ImportErpWorkOrderDetail::getMaterialCode));
        Map<String, ImportErpBom> parentBom = allBomTree.stream().collect(Collectors.toMap(ImportErpBom::getMaterialCode, Function.identity(), (e1, e2) -> e1));

        List<OrderBom> orderBomList = new ArrayList<>();

        Optional<ImportErpBom> firstOptional = bomChildren.stream().filter(e -> e.getIsTop() == 1).findFirst();
        if (!firstOptional.isPresent()) {
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点"));
//            errorList.add(new OrderExternalSyncErrorResVo(1, "找不到根节点：" + importErpOrder.getOrderCode(), importErpOrder.getOrderCode(), null, null, null, null,null, null, null, null, null));
            throw SyExceptionUtils.e("找不到BOM的根节点!");
        }
        ImportErpBom importErpBom = firstOptional.get();
        OrderBom top = swap(order, importErpBom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, null, errorList);
        String pattern = ".+" + WorkshopProp.PH_PATTERN;
        if (order.getOrderType() == 1 && !order.getMaterCode().matches(pattern)) {
            OrderBom o = orderBomMapper.lambdaQuery().eq(OrderBom::getMaterCode, order.getMaterCode()).eq(OrderBom::getOrderId, order.getId()).one();
            if (o == null) {
                OrderBom orderBom = new OrderBom();
                orderBom.setFactoryNo("170");
                orderBom.setOrderId(order.getId());
                orderBom.setMaterName(order.getMaterName());
                orderBom.setMaterCode(order.getMaterCode());

                int div = Integer.parseInt(importErpOrder.getQty()) / order.getOrderQty();
                if(Integer.parseInt(importErpOrder.getQty()) % order.getOrderQty() != 0){
                    throw SyExceptionUtils.e("订单数量必须为整数倍!");
                }

                if(div < 1){
                    throw SyExceptionUtils.e("当前数量必须大于等于订单数量!");
                }

                orderBom.setPartCount(new BigDecimal(div));
                orderBom.setTotalCount(orderBom.getPartCount());
                orderBom.setBomCode(order.getMaterCode());
                orderBom.setPlmId(order.getMaterCode());
                orderBom.setMaterType("Assembly");
                orderBom.setLevel(1);
                orderBom.setReadyType(1);
                orderBom.setDrawing(orderBom.getDrawing());

                StringBuilder sb = new StringBuilder();

                ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
                while (currentParent != null) {
                    ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                    if (importErpMater1 == null) {
                        // throw SyExceptionUtils.e("没有找到路径!");
//                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode()));
                        errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + currentParent.getMaterialCode(), importErpOrder.getOrderCode(), currentParent.getWorkOrderCode(), currentParent.getMaterialCode(), currentParent.getMaterialName(), null,String.format("%s%s", currentParent.getMaterial(), currentParent.getGrade()), currentParent.getPerReqQty(), currentParent.getPmCode(), currentParent.getStatusId(), null));
                    }
                    sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                    currentParent = parentBom.get(currentParent.getPmCode());
                }

                orderBom.setAssemblyPath(sb.toString());
                orderBom.setTopFlag(1);
                orderBom.setWorkChain("WW");
//
//                OrderPhase llPhase = new OrderPhase();
//                llPhase.setOrderId(order.getId());
//                llPhase.setBomId(orderBom.getId());
//                llPhase.setWorkTime(0);
//                llPhase.setWorkChain(orderBom.getWorkChain());
//                llPhase.setPhaseSeq(1);
//                llPhase.setMaterNo(orderBom.getMaterCode());
//                llPhase.setMaterName(orderBom.getMaterName());
//                llPhase.setPhaseCode(WorkshopProp.KJ_PHASE_CODE);
//                llPhase.setPhaseName(WorkshopProp.KJ_PHASE_NAME);
//                llPhase.setWorkGroupNumber(WorkshopProp.KJ_GROUP);
//                llPhase.setWorkChain(orderBom.getWorkChain());
//                orderPhaseMapper.insert(llPhase);

                OrderPhase topPhase = new OrderPhase();
                topPhase.setOrderId(order.getId());
                topPhase.setBomId(orderBom.getId());
                topPhase.setWorkTime(1);
                topPhase.setPhaseSeq(1);
                topPhase.setPhaseCode("WW");
                topPhase.setPhaseName("委外");
                topPhase.setWorkGroupNumber("WW");
                topPhase.setMaterNo(orderBom.getMaterCode());
                topPhase.setMaterName(orderBom.getMaterName());
                topPhase.setWorkChain(orderBom.getWorkChain());

                o = orderBom;
            }
            orderBomList.add(o);
            top.setPid(o.getId());

            orderBomList.add(top);
            top.setLevel(2);
            top.setTopFlag(0);
            top.setAssemblyPath(o.getAssemblyPath() + "/" + top.getDrawing());
            if(!StringUtils.hasText(top.getWorkChain())){
                top.setWorkChain("WW");
            }


        } else {
            orderBomList.add(top);
        }


        Map<String, List<ImportErpBom>> collect = bomChildren.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));
        List<OrderBom> orderBoms = Lists.newArrayList(top);

        while (!orderBoms.isEmpty()) {
            List<OrderBom> temp = Lists.newArrayList();
            for (OrderBom orderBom : orderBoms) {

                List<ImportErpBom> orderBoms1 = collect.get(orderBom.getBomCode());
                if (orderBoms1 == null) {
                    continue;
                }

                Map<String, OrderBom> map = new HashMap<>();
                for (ImportErpBom bom : orderBoms1) {
                    OrderBom swap = swap(order, bom, materCodeMap, workOrderCodeMap, workOrderDetailMap, bomPmCodeMap, erpMesOpMapping, parentBom, orderBom, errorList);
//                    if(orderBom.getWorkChain().equals("WL") && swap.getWorkChain().equals("WL")){
//                        continue;
//                    }

                    OrderBom bomHas = map.get(swap.getPlmId());
                    if(bomHas != null){
                        continue;
                    }
                    map.put(swap.getPlmId(), swap);

                    temp.add(swap);
                    orderBomList.add(swap);
                }
            }
            orderBoms = temp;

        }

        orderBomList.sort(Comparator.comparing(OrderBom::getBomCode));
        return orderBomList;


    }

    public Order conversionOrder(ImportErpOrder importErpOrder, ImportErpBom currentBom, ImportErpMater importErpMater, List<OrderExternalSyncErrorResVo> errorList) {
        Order order = new Order();
        order.setOrderCode(importErpOrder.getOrderCode());
        order.setConstructNo(importErpOrder.getOrderCode());
        order.setMaterCode(currentBom.getGraphNo());
        order.setMaterName(currentBom.getMaterialName());
        order.setOrderQty(NumberUtil.parseInt(importErpOrder.getQty()));
        order.setFinishQty(0);
        if (importErpOrder.getOrderCode().startsWith("J")) {
            order.setOrderType(4);
        } else {
            order.setOrderType(1);
        }
        order.setOrderStatus(1);
        order.setOrderDateTime(importErpOrder.getAssignDate());
        order.setDeliveryDateTime(importErpOrder.getDeliTime());
        order.setPlmId(importErpMater.getPlmId());

        order.setOrderPriority(1);
        order.setOrderWeight(1);

        return order;
    }

    public List<ImportErpWorkOrderDetail> getWorkOrderDetailMap(Integer erpOrderId, List<String> materCodeList) {

        QueryWrapper<ImportErpWorkOrderDetail> query = Wrappers.query();
        query.in("material_code", materCodeList);
        query.eq("erp_order_id", erpOrderId);
        return importErpWorkOrderDetailMapper.selectList(query);

    }

    public List<ImportErpWorkOrder> getWorkOrderMap(Integer erpOrderId, List<String> bomChildren) {

        LambdaQueryWrapper<ImportErpWorkOrder> query = Wrappers.lambdaQuery();
        query.in(ImportErpWorkOrder::getMaterialCode, bomChildren);
        query.eq(ImportErpWorkOrder::getErpOrderId, erpOrderId);
        return importErpWorkOrderMapper.selectList(query);

    }

    public List<ImportErpMater> getMaterMap(Integer erpOrderId, List<String> materCodeList) {

        QueryWrapper<ImportErpMater> query = Wrappers.query();
//        query.in("material_code", materCodeList);// 注意，此处不要取部分，要取全部
        query.eq("erp_order_id", erpOrderId);
        return importErpMaterMapper.selectList(query);
    }

    public List<ImportErpBom> findBomChildren(ImportErpBom currentBom) {
//
//        QueryWrapper<ImportErpBom> query = Wrappers.query();
//        query.ne("bom.status_id", "R");// 'Z21-010Z'
//        query.eq("bom.erp_order_id", currentBom.getErpOrderId());
////        query.eq("mater.erp_order_id", currentBom.getErpOrderId());
//        query.eq("bom.deleted", 0);
//        query.orderByAsc("mater.paint_code");
        List<ImportErpBom> importErpBoms = importErpBomMapper.tree(currentBom.getErpOrderId());

        Map<String, List<ImportErpBom>> pmCodeList = importErpBoms.stream().collect(Collectors.groupingBy(ImportErpBom::getPmCode));

        List<ImportErpBom> l = new ArrayList<>();

        List<ImportErpBom> temp = new ArrayList<>();
        temp.add(currentBom);
        currentBom.setIsTop(1);

        while (!temp.isEmpty()) {
            List<ImportErpBom> t = new ArrayList<>();
            for (ImportErpBom importErpBom : temp) {
                List<ImportErpBom> importErpBoms1 = pmCodeList.get(importErpBom.getMaterialCode());
                if (importErpBoms1 == null) {
                    continue;
                }
                for (ImportErpBom erpBom : importErpBoms1) {
                    erpBom.setIsTop(0);
                }
                t.addAll(importErpBoms1);
            }
            l.addAll(temp);
            temp = t;
        }
        return l;
    }

    public List<ImportErpBom> findAllTree(ImportErpOrder order) {
        return importErpBomMapper.selectList(Wrappers.<ImportErpBom>query().eq("erp_order_id", order.getId()));
    }

    public OrderBom swap(Order order, ImportErpBom bom, Map<String, ImportErpMater> materCodeMap, Map<String, List<ImportErpWorkOrder>> workOrderCodeMap, Map<String, List<ImportErpWorkOrderDetail>> workOrderDetailMap, Map<String, List<ImportErpBom>> bomPmCodeMap, Map<String, Map<String, ImportErpMapping>> erpMesOpMapping, Map<String, ImportErpBom> parentBom, OrderBom parent, List<OrderExternalSyncErrorResVo> errorList) {

        OrderBom orderBom = new OrderBom();
        orderBom.setFactoryNo("170");
        orderBom.setOrderId(order.getId());
        orderBom.setPackCenter(bom.getPickCenter());
        orderBom.setMaterName(bom.getMaterialName());
        orderBom.setStandards(bom.getGrade());
        orderBom.setErpCode(bom.getMaterialCode());
        orderBom.setErpParentCode(bom.getPmCode());
        orderBom.setPartCount(NumberUtil.round(bom.getPerReqQty(), 0));
        orderBom.setTopFlag(bom.getIsTop());
        orderBom.setBomCode(bom.getMaterialCode());
        orderBom.setParentBomCode(bom.getPmCode());
        if (parent == null) {
            orderBom.setTotalCount(orderBom.getPartCount());
            orderBom.setLevel(1);
        } else {
            orderBom.setTotalCount(new BigDecimal(bom.getReqQty()));
            orderBom.setLevel(parent.getLevel() + 1);
        }

        ImportErpMater importErpMater = materCodeMap.get(bom.getMaterialCode());
        if (importErpMater == null) {
//            throw SyExceptionUtils.e("找不到对应的物料信息");
            orderBom.setMaterCode(bom.getGraphNo());
            if(StringUtils.hasText(orderBom.getMaterCode())){
                orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
            }
            orderBom.setPlmId(orderBom.getMaterCode());
            orderBom.setDrawing(orderBom.getMaterCode());
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(2);
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
//            errorList.add(new OrderExternalSyncErrorResVo(2, "找不到零件信息：" + bom.getMaterialCode(), order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), null));
            return orderBom;
        }

        orderBom.setMaterCode(importErpMater.getPaintCode());
        if(StringUtils.hasText(orderBom.getMaterCode())){
            orderBom.setMaterCode(orderBom.getMaterCode().replaceAll("/", "-"));
        }


        orderBom.setPlmId(importErpMater.getPlmId());
        if (orderBom.getPlmId() == null) {
            orderBom.setPlmId("");
        }
        if(StringUtils.hasText(orderBom.getPlmId())){
            orderBom.setPlmId(orderBom.getPlmId().replaceAll("/", "-"));
        }

        if (importErpMater.getNetWeight() != null) {
            orderBom.setMaterWeight(NumberUtil.round(importErpMater.getNetWeight(), 2));
        }

        orderBom.setDrawing(importErpMater.getPaintCode());
        if(StringUtils.hasText(orderBom.getDrawing())){
            orderBom.setDrawing(orderBom.getDrawing().replaceAll("/", "-"));
        }


        List<ImportErpWorkOrder> workOrderList = workOrderCodeMap.get(bom.getMaterialCode());
        ImportErpWorkOrder workOrder = null;
        if (CollUtil.isNotEmpty(workOrderList)) {
            workOrder = findDueDate(workOrderList);
            if (workOrder != null) {
                orderBom.setDueDate(workOrder.getPlanEndTime());
            }
        }

        if (workOrder == null) {
            workOrder = new ImportErpWorkOrder();
            workOrder.setIsComponent("1");
            workOrder.setWorkOrderCode("WO-XXXXXXX");
            workOrder.setWorkOrderType("1");
//                    orderBom.setDueDate(bom.getMarkDate());// 代码有问题，ERP没这个字段，所有注释
        }


        List<ImportErpWorkOrderDetail> workOrderDetailList = workOrderDetailMap.get(bom.getMaterialCode());
        // 如果无工序明细，则为外协件
        if (workOrderDetailList == null) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : 1);
        }

        String spec = importErpMater.getSpec();//.replaceAll(REGEX_CHINESE, "");
        if (spec != null) {
            if (spec.contains("组件")) {
                orderBom.setMaterType("Assembly"); // 组件类型，Assembly
            } else if (workOrderDetailList == null) {
                //如果无工序明细，则为外协件
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            } else if (spec.contains("δ")) {
                orderBom.setMaterType("Platepart");//Platepart
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);

                //施工单 物料号  获取 工单bom
                List<ImportErpBom> plateList = bomPmCodeMap.get(bom.getMaterialCode());
                if (plateList == null || plateList.isEmpty()) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "找不到对应的板材材质或规格信息", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("找不到对应的板材材质或规格信息");
                } else {
                    ImportErpBom plateBom = plateList.get(0);
                    if (StringUtils.hasText(plateBom.getMaterial()) && StringUtils.hasText(plateBom.getGrade())) {
                        orderBom.setTexture(plateBom.getMaterial());//材质
                        String str = plateBom.getGrade().replace("δ", "");
                        try {
                            orderBom.setMaterHigh(NumberUtil.round(str, 0).intValue());//厚度

                        } catch (Exception e) {
                            e.printStackTrace();
                            throw e;
                        }
                    } else {
                        errorList.add(new OrderExternalSyncErrorResVo(2, "材质或规格为空", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                        return orderBom;
//                        throw SyExceptionUtils.e("材质或规格为空");
                    }


                }
            } else {
                orderBom.setMaterType("Component");
                orderBom.setWorkChain("WL");//外协件定值
                orderBom.setReadyType("1".equals(workOrder.getIsComponent()) ? 2 : 1);
            }
        }

        //工单类型0-自制；1-外协
        if (workOrder.getWorkOrderType().equals("1")) {
            orderBom.setMaterType("Component");
            orderBom.setWorkChain("WL");//外协件定值
            orderBom.setReadyType(workOrder.getIsComponent().equals("1") ? 2 : null);
        }

        if (orderBom.getMaterType() == null) {
            errorList.add(new OrderExternalSyncErrorResVo(2, "无法判断物料类型!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
            return orderBom;
//            throw SyExceptionUtils.e("无法判断物料类型!");
        }

//            orderBom.setParentMaterNo(orderBom.getDrawing());
        //获取工序链
        if (!orderBom.getMaterType().equals("Component")) {
            String workChain = getWorkChain(workOrderDetailList, erpMesOpMapping, workOrder.getWorkOrderCode(), orderBom, errorList);
            orderBom.setWorkChain(workChain);
        }


        //ERP工单号
        orderBom.setWorkOrderCode(workOrder.getWorkOrderCode());

        // MES需要的路径，如果没用请注释
        if (orderBom.getTopFlag().equals(1)) {
            StringBuilder sb = new StringBuilder();

            ImportErpBom currentParent = parentBom.get(orderBom.getBomCode());
            while (currentParent != null) {
                ImportErpMater importErpMater1 = materCodeMap.get(currentParent.getMaterialCode());
                if (importErpMater1 == null) {
                    errorList.add(new OrderExternalSyncErrorResVo(2, "没有找到路径!", order.getConstructNo(), bom.getWorkOrderCode(), bom.getMaterialCode(), bom.getMaterialName(), null,String.format("%s%s", bom.getMaterial(), bom.getGrade()), bom.getPerReqQty(), bom.getPmCode(), bom.getStatusId(), bom.getMaterialCode()));
                    return orderBom;
//                    throw SyExceptionUtils.e("没有找到路径!");
                }
                sb.insert(0, importErpMater1.getPlmId()).insert(0, "/");
                currentParent = parentBom.get(currentParent.getPmCode());
            }

            orderBom.setAssemblyPath(sb.toString());
        } else {
            orderBom.setAssemblyPath(parent.getAssemblyPath() + "/" + orderBom.getMaterCode());
            orderBom.setPid(parent.getId());
        }

        orderBom.setReadyType(orderBom.getWorkChain().equals("WL") ? 2 : 1);

        return orderBom;
    }


    public String getWorkChain(List<ImportErpWorkOrderDetail> allWorkOrderDetailList, Map<String, Map<String, ImportErpMapping>> erpMesOpMappingMap, String workOrderCode, OrderBom bom, List<OrderExternalSyncErrorResVo> errorList) {
        String workChain = "";
        if (CollUtil.isEmpty(allWorkOrderDetailList)) {
            return workChain;
        }

        List<ImportErpWorkOrderDetail> detailList = allWorkOrderDetailList
                .stream()
                .filter(e -> !"70020604".equals(e.getOpCode()))
                .filter(e -> !"Z105".equals(e.getOp()))
                .filter(e -> workOrderCode.equals(e.getWorkOrderCode()))
                .sorted(Comparator.comparing(ImportErpWorkOrderDetail::getSeq))
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(detailList)) {
            return workChain;
        }

        Map<String, Integer> phaseCount = new HashMap<>();
        for (ImportErpWorkOrderDetail detail : detailList) {

            if (!StringUtils.hasText(detail.getOpCode())) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
//                errorList.add("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }
            if (!StringUtils.hasText(detail.getOp())) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
//                errorList.add("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }

            if (detail.getOpCode().startsWith("129")) {
                workChain += "ZP-";//如果工作中心以129开头，直接截断后续所有工序，增加ZP工序
                break;
            }

            if(!detail.getOpCode().trim().startsWith("170")){
                continue;
            }

            if (erpMesOpMappingMap.get(detail.getOpCode()) == null) {
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
                return workChain;
            }
            ImportErpMapping importErpMapping = erpMesOpMappingMap.get(detail.getOpCode()).get(detail.getOp());

            if (importErpMapping == null) {
                errorList.add(new OrderExternalSyncErrorResVo(4, detail.getMaterialName() + detail.getMaterialCode() + "工作中心编码【" + detail.getOpCode() + "】,缺工序编码【" + detail.getOp() + "】,请先维护工作中心映射!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
//                throw SyExceptionUtils.e("根据ERP工作中心编码“" + detail.getOpCode() + "”,ERP工序编码“" + detail.getOp() + "”,物料编码“" + detail.getMaterialCode() + "”未能找到对应的MES工作中心映射关系，请先维护工作中心映射!");
            } else {
                String str = importErpMapping.getMesWorkPhase();
                Integer count = phaseCount.compute(str, (k, v) -> v == null ? 0 : v + 1);
                String phaseCodeCount = str + "-";
                if (count > 0) {
                    phaseCodeCount = str + String.format("%02d", count) + "-";
                }
                workChain += phaseCodeCount;
            }
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(workChain)) {
            workChain = workChain.substring(0, workChain.length() - 1);
        } else {
//            throw SyExceptionUtils.e("工序链生成失败！");
            errorList.add(new OrderExternalSyncErrorResVo(4, "工序链生成失败!", null, bom.getWorkOrderCode(), bom.getMaterCode(), bom.getMaterName(), bom.getPlmId(), bom.getStandards(), bom.getPartCount().toString(), bom.getErpParentCode(), null, bom.getDrawing()));
        }


        return workChain;
    }
    public ImportErpWorkOrder findDueDate(List<ImportErpWorkOrder> infoList) {
        if (infoList.size() == 1) {
            return infoList.get(0);

        }

        //过滤掉 3 和4  已取消的
        List<ImportErpWorkOrder> collectList = infoList
                .stream()
                .filter(s -> !s.getWorkOrderState().equals("3") && !s.getWorkOrderState().equals("4"))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collectList)) {
            return collectList.get(0);
        }

        //如果没有 就获取 计划开始时间不为空的
        for (ImportErpWorkOrder orderInfo : infoList) {
            if (orderInfo.getPlanStartTime() != null) {
                return orderInfo;
            }
        }
        return null;
    }

    @Override
    public String getCode() {
        return ERP_CODE;
    }
}
